package xyvcard;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;

public class JavaCompilerHelper {

  public static CompileResult compileFromString(String sourceCode, String outputDir)
      throws IOException {
    Pattern pattern =
        Pattern.compile("(?m)^\\s*public\\s+class\\s+([A-Za-z_$][A-Za-z0-9_$]*)\\s*\\{");
    Matcher matcher = pattern.matcher(sourceCode);

    if (!matcher.find()) {
      return new CompileResult("",false, "源代码中未找到公共类定义.");
    }

    String className = matcher.group(1);

    // 获取JavaCompiler实例
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    // 创建内存中的Java源代码对象
    SimpleJavaFileObject fileObject = new SimpleJavaSourceCodeObject(className, sourceCode);

    // 创建标准文件管理器
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

    // 设置输出目录
    fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(outputDir)));

    // 创建源代码文件对象列表
    Iterable<? extends JavaFileObject> compilationUnits = Collections.singletonList(fileObject);

    // 创建编译任务
    DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
    JavaCompiler.CompilationTask task = compiler.getTask(null, // 输出流，默认为System.err
        fileManager, diagnostics, // 添加诊断监听器来收集编译错误和警告
        null, // 不设置额外编译选项
        null, // 注解处理器
        compilationUnits);
    try {
      // 执行编译任务
      boolean success = task.call();

      // 处理编译结果
      if (success) {
        return new CompileResult(className,true, "源代码已成功编译为字节码文件，并保存在 " + outputDir + " 目录下");
      } else {
        StringBuilder errorMessage = new StringBuilder("编译失败. 错误信息如下:\n");
        for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
          errorMessage.append(diagnostic).append('\n');
        }
        return new CompileResult(className,false, errorMessage.toString());
      }
    }

    finally {
      // 关闭文件管理器
      try {
        fileManager.close();
      } catch (IOException e) {
        System.err.println("关闭文件管理器时发生错误: " + e.getMessage());
      }
    }
  }



}
